﻿using EFCoreRepository.DbContexts;
using IdentityModel;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

using ThoughtWorks.QRCode.Codec;
using Zoomtel.Entity;
using Zoomtel.Entity.BIZ;
using Zoomtel.Persist.BIZ;
using Zoomtel.Persist.BIZ.Models;
using Zoomtel.Service.Auth;
using Zoomtel.Service.BIZ.ViewModels;
using Zoomtel.Utils;

namespace Zoomtel.Service.BIZ
{
    public class AgentInfoService
    {

        #region 颁发Token
        private UserTokenResult Token(AgentInfoEntity model)
        {

            var tokenHandler = new JwtSecurityTokenHandler();

            var key = Encoding.UTF8.GetBytes(_jwtSettings.SecretKey);
            var authTime = DateTime.Now;//授权时间
            var expiresAt = authTime.AddDays(30);//过期时间
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                    new Claim(JwtClaimTypes.Audience,_jwtSettings.Audience),
                    new Claim(JwtClaimTypes.Issuer,_jwtSettings.Issuer),
                     new Claim(JwtClaimTypes.Name, model.AgentPhoneNum),

                    new Claim(Zoomtel.Service.Auth.ClaimTypes.LoginName,model.AgentPhoneNum),
                    new Claim(Zoomtel.Service.Auth.ClaimTypes.Uid,model.Id.ToString()),
                    new Claim(Zoomtel.Service.Auth.ClaimTypes.LoginTime,authTime.ToString())

                //new Claim(JwtClaimTypes.Name, model.LoginName),
                //new Claim(JwtClaimTypes.Id, model.Uid.ToString())
            }),
                Expires = expiresAt,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            UserTokenResult result = new UserTokenResult();
            result.access_token = tokenString;
            result.expires_at = expiresAt;
            result.name = model.AgentPhoneNum;
            result.uid = model.Id;

            return result;
        }

        #endregion
        #region 微信相关
        //心智数据
        string APPID = "wxe58b825d6e17e63c";
        string APPSECRET = "c49bfda307d62df7e587bb901f6c655e";

        public string getAccessToken()
        {
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", APPID, APPSECRET);
            string access_token = _cache.Get<string>("wechat_access_token");
            if (access_token.IsNull())
            {
                string result = Zoomtel.Utils.Helpers.HttpHelper.HttpGet(url);
                var resultModel = JsonConvert.DeserializeObject<JObject>(result);
                access_token = resultModel["access_token"].ToString();
                _cache.Set<string>("wechat_access_token", access_token, 10);

            }
            return access_token;

        }
        private void writeLog(string txt)
        {
            File.AppendAllText("c:\\log.txt", txt+"\r\n" );
         

        }

        public JObject getWeChatUserInfo(string openid,string access_token)
        {
            string userInfoUrl = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN", access_token, openid);


            string userInfoResult = Zoomtel.Utils.Helpers.HttpHelper.HttpGet(userInfoUrl);
            writeLog("userInfoResult:" + userInfoResult);

            var userInfoModel = JsonConvert.DeserializeObject<JObject>(userInfoResult);
            return userInfoModel;

        }

        public JObject codeGetUserInfo(string code, bool onlyOpenId = false)
        {
            string url = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code", APPID, APPSECRET, code.TrimEnd());
            string access_token = "";
            //writeLog("access_token:" + access_token);
            //string access_token = "";
            string openid = "";
            //if (access_token.IsNull())
            //{
            writeLog("access_token:null");
            string result = Zoomtel.Utils.Helpers.HttpHelper.HttpGet(url);
            writeLog("result:" + result);

            var resultModel = JsonConvert.DeserializeObject<JObject>(result);



            access_token = resultModel["access_token"].ToString();
            openid = resultModel["openid"].ToString();
            writeLog("openid:" + openid);

            //_cache.Set<string>("wechat_access_token", access_token, 10);
            if (onlyOpenId)
            {
                return resultModel;
            }
            //}

            string userInfoUrl = string.Format("https://api.weixin.qq.com/sns/userinfo?access_token={0}&openid={1}&lang=zh_CN", access_token, openid);


            string userInfoResult = Zoomtel.Utils.Helpers.HttpHelper.HttpGet(userInfoUrl);
            writeLog("userInfoResult:" + userInfoResult);

            var userInfoModel = JsonConvert.DeserializeObject<JObject>(userInfoResult);
            return userInfoModel;
        }

        #endregion

        #region 二维码相关

        private string GetQrcode(string id, string url)
        {
            string filename = id + ".jpg";
            string filepath = "/upload/qrcode/" + filename;
            string allpath = host.WebRootPath + filepath;
            System.Drawing.Bitmap image = null;
            if (File.Exists(allpath))
            {
                image = new Bitmap(allpath);

            }
            else
            {

                QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
                qrCodeEncoder.QRCodeScale = 4;
                qrCodeEncoder.QRCodeVersion = 8;
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
                //System.Drawing.Image image = qrCodeEncoder.Encode("4408810820 深圳－广州 小江");
                image = qrCodeEncoder.Encode(url, Encoding.Default);


                System.IO.FileStream fs = new System.IO.FileStream(allpath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
                image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);

                fs.Close();
                //image.Dispose();
            }
            return ImgToBase64String(image);
            //二维码解码
            //var codeDecoder = CodeDecoder(filepath);


        }

        /// <summary>
        /// 文件转Base64码
        /// </summary>
        /// <param name="fileLocation"></param>
        /// <returns></returns>
        private string ImgToBase64String(Bitmap bmp)
        {
            MemoryStream ms = new MemoryStream();
            try
            {
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                return Convert.ToBase64String(arr);
            }
            catch (Exception ex)
            {
                //Log.WriteLog4Ex("图片转base64", ex);
                return "";
            }
            finally
            {
                ms.Close();
            }
        }
        #endregion

        public async Task<IResultModel> Query(AgentQueryModel model)
        {
            var result = await _agentInfoRepository.Query(model);

            return ResultModel.Success(result);
        }
        
        public async Task<IResultModel> UpdateBalance(AgentInfoEntity model)
        {
            var agentInfo = await _agentInfoRepository.FindEntityAsync(model.Id);
            decimal balance = agentInfo.AccountBalance;
            decimal diff = model.AccountBalance - balance;
            return await ChangeBalance(model.Id,ChangeType.ManualAlter.ToString(),diff,"","手动修改", _defaultDbContext.LoginInfo.LoginName);
        }

        public async Task<IResultModel> UpdateStatus(string ids, string status)
        {
            List<string> idList = ids.Split(',').ToList();
            var result = await _agentInfoRepository.FindListAsync(a => idList.Contains(a.Id));
            int success = 0;
            _agentInfoRepository.BeginTrans();
            foreach (var item in result)
            {
                
                item.Status = status;
                success = success + _agentInfoRepository.Update(item);
                
            }
            if (success > 0)
            {
                _agentInfoRepository.Commit();
                return new ResultModel<int>().Success(success);
            }
            else
            {
                _agentInfoRepository.Rollback();
                return new ResultModel<int>().Failed();
            }
        }

        public async Task<IResultModel> Update(AgentInfoEntity model)
        {
            var result = new ResultModel<int>();

            int i = _agentInfoRepository.Update(model);
            if (i > 0)
            {
                return result.Success(i);
            }
            else
            {
                return result.Failed();
            }
        }

        private DefaultDbContext _defaultDbContext;
        private ChangeBalanceRepository _changeBalanceRepository;
        private AgentInfoRepository _agentInfoRepository;
        private CashLogRepository _cashLogRepository;
        private BankInfoRepository _bankInfoRepository;
        private Sms.SmsService _smsSv;
        private Zoomtel.Cache.ICacheHandler _cache;
        private JwtSettings _jwtSettings;
        private IHostingEnvironment host = null;

        private readonly ILoginInfo _loginInfo;//这里主要获取IP 和浏览器信息

        public AgentInfoService(IOptions<JwtSettings> _jwtSettingsAccesser, IHostingEnvironment _host,BankInfoRepository bankInfoRepository, AgentInfoRepository agentInfoRepository, CashLogRepository cashLogRepository, ChangeBalanceRepository changeBalanceRepository, DefaultDbContext defaultDbContext, Sms.SmsService smsSv, Zoomtel.Cache.ICacheHandler cache, ILoginInfo loginInfo)
        {
            _jwtSettings = _jwtSettingsAccesser.Value;
            _agentInfoRepository = agentInfoRepository;
            _changeBalanceRepository = changeBalanceRepository;
            _cashLogRepository = cashLogRepository;
            _bankInfoRepository = bankInfoRepository;
            _cache = cache;
            _smsSv = smsSv;
            _loginInfo = loginInfo;

          
            _defaultDbContext = defaultDbContext;
            host = _host;
        }

        public async Task<IResultModel> Add(AgentInfoEntity model)
        {
            var result = new ResultModel<int>();

            model.Id = _agentInfoRepository.GetSeq("S_BIZ_AGENTINFO").ToString();

            int i = _agentInfoRepository.Insert(model);
            if (i > 0)
            {

                return result.Success(i);
            }
            else
            {
                return result.Failed();

            }

        }
        /// <summary>
        /// 余额变更
        /// </summary>
        /// <param name="agentId"></param>
        /// <param name="changeType"></param>
        /// <param name="amount">金额分正负</param>
        /// <param name="billNo"></param>
        /// <param name="remarks"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        public async Task<IResultModel> ChangeBalance(string agentId, string changeType, decimal amount, string billNo, string remarks, string userName)
        {
            try
            {
                //查询分销商信息
                var agentInfoEntity = _agentInfoRepository.QueryEntity(agentId);
                //添加余额变更记录
                ChangeBalanceEntity changeBalanceEntity = new ChangeBalanceEntity();

                changeBalanceEntity.Id = _agentInfoRepository.GetSeq("S_BIZ_CHANGEBALANCE").ToString();
                changeBalanceEntity.AgentId = agentId;
                changeBalanceEntity.Type = changeType;//10 收益  20提现  30提现驳回  40计算撤回  50手动修改
                changeBalanceEntity.Amount = amount;

                changeBalanceEntity.Balance = agentInfoEntity.AccountBalance + amount;
                changeBalanceEntity.Remarks = remarks;
                changeBalanceEntity.BillNo = billNo;
                changeBalanceEntity.CreatedTime = DateTime.Now;
                changeBalanceEntity.Creator = userName;

                //插入变更表记录
                await _changeBalanceRepository.InsertAsync(changeBalanceEntity);

                //更新余额
                agentInfoEntity.AccountBalance = changeBalanceEntity.Balance;
                //提现和提现驳回需要回滚lockbalance
                if (changeType.Equals(ChangeType.UserCarryRollBack.ToString())|| changeType.Equals(ChangeType.UserCarry.ToString())) {
                    agentInfoEntity.LockBalance = agentInfoEntity.LockBalance + amount * -1;
                }
                await _agentInfoRepository.UpdateAsync(agentInfoEntity);

                return ResultModel.Success();
            }
            catch (Exception e)
            {
                return ResultModel.Failed();
            }
            return ResultModel.Failed();

        }
        public async Task<IResultModel> RegisterBind(ViewModels.AgentBindRegisterModel model)
        {
            //var result = new ResultModel<UserTokenResult>();

            //1、验证验证码是否正确
            if (model.Captcha.IsNull())
            {
                return ResultModel.Failed("短信验证码不能为空！");


            }
            if (!RegexHelper.CheckInput(model.Phone, RegexHelper.IS_VALID_MOBILE))
            {
                return ResultModel.Failed("请输入正确的手机号码");


            }

            //string smsResult = _smsSv.GetModelAndCp(model.Phone, model.Captcha, "register");
            //if (smsResult != "ok")
            //{
            //    return ResultModel.Failed("短信验证失败：" + smsResult);

            //}



            //2、查手机号码是否存在
            if (_agentInfoRepository.Exists(a => a.AgentPhoneNum == model.Phone))
            {

                return ResultModel.Failed("手机号码已经被注册！");
            }
            //3、根据code获取用户微信信息
            if (model.OpenId.IsNull())
            {
                return ResultModel.Failed("微信OpenId为空！");


            }
            if (model.Access_Token.IsNull())
            {
                return ResultModel.Failed("微信Access_Token为空！");


            }
            JObject userInfo = getWeChatUserInfo(model.OpenId,model.Access_Token);
            if (userInfo.Value<int>("errcode") != 0)
            {

                return ResultModel.Failed("获取微信用户信息出错！");

            }


            //4、查询openid是否绑定
            string openid = userInfo.Value<string>("openid");
            string nickName = userInfo.Value<string>("nickname");
            string avatar = userInfo.Value<string>("headimgurl");
            string city = userInfo.Value<string>("city");
            string province = userInfo.Value<string>("province");
            if (_agentInfoRepository.Exists(a => a.AgentWechatId == openid))
            {

                return ResultModel.Failed("此微信号已经绑定本平台！");
            }
            //5、组织插入分销商记录
            Zoomtel.Entity.BIZ.AgentInfoEntity entity = new AgentInfoEntity();
            entity.Id = _agentInfoRepository.GetSeq("S_BIZ_AGENTINFO").ToString();

            entity.AgentCode = model.Phone;
            entity.AgentPhoneNum = model.Phone;

            entity.AccountBalance = 0;
            entity.LockBalance = 0;
            entity.AgentName = nickName;
            entity.Avatar = avatar;
            entity.City = city;
            entity.Province = province;
            entity.AgentWechatId = openid;
            entity.LastTime = entity.CreatedTime = DateTime.Now;
            entity.LastIP = entity.CreateIP = _loginInfo.IP;
            entity.LoginCount = 0;


            //5.1 是否存在上级ID ,存在则查询上级用户是否存在 且未被禁用
            if (!model.UpperId.IsNull())
            {
                var upperModel = _agentInfoRepository.FindEntity(a => a.Id == model.UpperId);
                if (upperModel != null && upperModel.Status == "1")
                {
                    entity.UpperId = model.UpperId;

                }
            }

            int result = await _agentInfoRepository.InsertAsync(entity);
            if (result > 0)
            {
                return ResultModel.Success("注册成功！");
            }
            return ResultModel.Failed();
        }

        public async Task<IResultModel> UnBind()
        {
            var model = _agentInfoRepository.FindEntity(a => a.Id == _loginInfo.Uid);
            if (model == null)
            {
                return ResultModel.Failed("未找到账号！");
            }
            model.AgentWechatId = "";

          int i= await _agentInfoRepository.UpdateAsync(model);
            if (i > 0)
            {
                return ResultModel.Success("");

            }
            else
            {
                return ResultModel.Failed("保存失败");
            }
        }


        public async Task<IResultModel<UserTokenResult>> LoginByChildrenUid(string ChildrenUid)
        {
            var result = new ResultModel<UserTokenResult>();
         var user=   _agentInfoRepository.FindEntity(a => a.Id == ChildrenUid);
           if(user.UpperId == _loginInfo.Uid)
            {
                if (user == null)
                {
                  
                    return result.Failed("分销商信息不存在");

                    //return result.Failed(openid);
                    //return result.Failed("账户不存在");
                }
                if (user.Status == "0")
                {
                    return result.Failed("账户未启用");
                }
                writeLog("开始修改:");
                writeLog("loginIP:" + _loginInfo.IP);
                //修改用户登陆信息
                user.LoginCount++;
                user.LastIP = _loginInfo.IP;
                try
                {
                    _agentInfoRepository.Update(user);// 这里要加上await 可能出现错误
                }
                catch (Exception ex)
                {

                    writeLog("ex:" + ex.Message);
                }
                writeLog("修改成功:");

                if (user != null)
                {
                    writeLog("开发颁发TOKEN:");

                    var obj = Token(user);
                    writeLog("开发颁发TOKENend:" + obj.ToString());

                    return result.Success(obj, "已注册");
                }
                else
                {
                    return result.Failed("登陆失败");
                }

            }
            else
            {
                return result.Failed("无权限登陆");
            }

        }

        public async Task<IResultModel<UserTokenResult>> LoginByCode(string code)
        {
            var result = new ResultModel<UserTokenResult>();

            //return result.Failed("微信Code为空！");

            if (code.IsNull())
            {
                return result.Failed("微信Code为空！");


            }

            JObject userInfo = codeGetUserInfo(code,true);
            var openid = userInfo["openid"].ToString();
            var access_token = userInfo["access_token"].ToString();
            writeLog("resultopenid:" + openid);


            var user = await _agentInfoRepository.GetByWechatId(openid);
            if (user == null)
            {
                UserTokenResult obj = new UserTokenResult();
                obj.access_token = access_token;
                obj.uid = openid;
                return result.Success(obj,"未注册");

                //return result.Failed(openid);
                //return result.Failed("账户不存在");
            }
            if (user.Status == "0")
            {
                return result.Failed("账户未启用");
            }
            writeLog("开始修改:" );
            writeLog("loginIP:" + _loginInfo.IP);
            //修改用户登陆信息
            user.LoginCount++;
            user.LastIP = _loginInfo.IP;
            try
            {
                _agentInfoRepository.Update(user);// 这里要加上await 可能出现错误
            }
            catch (Exception ex)
            {

                writeLog("ex:"+ex.Message);
            }
            writeLog("修改成功:");

            if (user != null)
            {
                writeLog("开发颁发TOKEN:");

                var obj = Token(user);
                writeLog("开发颁发TOKENend:"+obj.ToString());

                return result.Success(obj,"已注册");
            }
            else
            {
               return result.Failed("登陆失败");
            }
        }

        public async Task<IResultModel> GetAgentProfitRank()
        {
            List<AgentProfitRankModel> resultList = new List<AgentProfitRankModel>();
         var list=await   _agentInfoRepository.GetProfitRank();
            list.ForEach(a =>
            {
                resultList.Add(new AgentProfitRankModel()
                {
                    Avatar = a.Avatar,
                    UserName = a.AgentName,
                    Profit = a.AccountBalance
                });
            });

            return ResultModel.Success(resultList);
        }

        /// <summary>
        /// 获取子分销商列表
        /// </summary>
        /// <returns></returns>
        public async Task<IResultModel> GetChildrenAgent()
        {

            var list =  _agentInfoRepository.FindList(a=>a.UpperId==_loginInfo.Uid);
            return ResultModel.Success(list);

        }

        /// <summary>
        /// 用户申请提现
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public async Task<IResultModel> CashApply(decimal num)
        {
            var bankInfoEntity = _bankInfoRepository.FindEntity(a => a.AgentId == _loginInfo.Uid);
            if (bankInfoEntity == null)
            {
                return ResultModel.Failed("未设置收款信息!");
            }
            if (bankInfoEntity.Status != "10")
            {

                return ResultModel.Failed("收款信息未审核!");

            }

            AgentInfoEntity agentEntity = _agentInfoRepository.FindEntity(_loginInfo.Uid);
            if (num <= 50)
            {
                return ResultModel.Failed("最低提现金额为50元!");


            }
            if (agentEntity.AccountBalance < num)
            {

                return ResultModel.Failed("您的可提现金额不足!");
            }
            CashLogEntity log = new CashLogEntity();
            log.Createtime = DateTime.Now;
            log.Money = num;
            log.Status = "0";
            log.Transfer_Money = 0;
            log.Fee_Rate = 0;
            log.Transfer_Fee = 0;//
            log.Uid = _loginInfo.Uid;
            log.Id = _cashLogRepository.GetSeq("S_BIZ_CASHLOG").ToString();
            _cashLogRepository.BeginTrans();
          int result=  await _cashLogRepository.InsertAsync(log);
            if (result > 0)
            {

                var changeBanlanceResult = await ChangeBalance(_loginInfo.Uid, ChangeType.UserCarry.ToString(),- num, "", "提现冻结", "");
                if (!changeBanlanceResult.Successful)
                {
                    _cashLogRepository.Rollback();
                    return ResultModel.Failed();
                }
                else
                {
                    _cashLogRepository.Commit();
                    return ResultModel.Success();

                }
            }
            return ResultModel.Failed();
        }


        public async Task<IResultModel<AgentInfoPubModel>> GetUserInfo(string Uid)
        {
            if (Uid.IsNull())
            {
                Uid = _loginInfo.Uid;
            }
            ResultModel<AgentInfoPubModel> result = new ResultModel<AgentInfoPubModel>();
            var model=  await _agentInfoRepository.GetAgentInfo(Uid);
            model.web_qrcode = GetQrcode(model.Id, "https://agent.xinzhidata.com/assets/addons/mental/index.html#/pages/member/member?upperid="+Uid);
            return result.Success(model);
        }

   
    }
}
